﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;

namespace MuYue.Config
{
    /// <summary>
    /// 配置统一管理器
    /// </summary>
    public class AppConfigManager
    {
        #region 私有字段
        /// <summary>
        /// 配置从属的管理器的名字
        /// 创建的时候首先进行全缓存集合查询
        /// 如果存在这个管理器就直接获取
        /// 如果没有就新建
        /// </summary>
        private string mManagerName;
        /// <summary>
        /// 缓存配置的容器
        /// </summary>
        private List<AppConfigModel> mAppConfigContainer;
        /// <summary>
        /// 所有创建的了的Manger的集合
        /// </summary>
        private static ConcurrentBag<AppConfigManager> mManagerCacheContainer = new ConcurrentBag<AppConfigManager>();
        #endregion

        #region 构造函数
        private AppConfigManager(string managerName)
        {
            this.mManagerName = managerName;
            //初始化
            if (SqliteReadEvent == null)
                throw new Exception("配置管理器没有提供配置数据获取方式");
            mAppConfigContainer = SqliteReadEvent(this.mManagerName);
        }

        /// <summary>
        /// 管理器创建
        /// </summary>
        /// <param name="managerName"></param>
        /// <returns></returns>
        public static AppConfigManager Create(string managerName)
        {
            lock (mManagerCacheContainer)
            {
                foreach (var t in mManagerCacheContainer)
                    if (t.mManagerName == managerName)
                        return t;
                var manager = new AppConfigManager(managerName);
                mManagerCacheContainer.Add(manager);
                return manager;
            }
        }
        #endregion

        #region 外接事件
        /// <summary>
        /// 数据库读取委托
        /// </summary>
        /// <param name="managerName"></param>
        /// <returns></returns>
        internal delegate List<AppConfigModel> AppConfigReadDelegate(string managerName);
        /// <summary>
        /// 数据库写入委托
        /// </summary>
        /// <param name="config"></param>
        internal delegate void AppConfigWriteDelegate(AppConfigModel config);
        /// <summary>
        /// 从数据库读取数据
        /// </summary>
        internal static event AppConfigReadDelegate SqliteReadEvent;
        /// <summary>
        /// 新建配置数据
        /// </summary>
        internal static event AppConfigWriteDelegate InsertConfigItemEvent;
        /// <summary>
        /// 更新配置数据
        /// 将数据持久化到数据库
        /// </summary>
        internal static event AppConfigWriteDelegate UpdateConfigItemEvent;
        #endregion

        /// <summary>
        /// 获取配置项
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public AppConfig<T> GetConfig<T>(string key, T defaultValue)
        {
            foreach (var t in mAppConfigContainer)
            {
                if (t.Key == key)
                    return new AppConfig<T>(t, defaultValue, Update);
            }

            var model = new AppConfigModel {
                MangerName = this.mManagerName,
                Key = key,
                Value = defaultValue.ToString()
            };
            //新建key
            mAppConfigContainer.Add(model);
            if (InsertConfigItemEvent != null)
                InsertConfigItemEvent(model);
            return new AppConfig<T>(model, defaultValue, Update);

        }

        /// <summary>
        /// 给AppConfig<T>进行的数据调用
        /// </summary>
        /// <param name="config"></param>
        private void Update(AppConfigModel config)
        {
            if (UpdateConfigItemEvent != null)
                UpdateConfigItemEvent(config);
        }
    }
}
